#pragma once

#include <map>
#include <mutex>
namespace Hi {
template <typename T> class HiCollection {
  public:
    T map_;
    std::mutex mutex_;

  public:
    int size() {
        std::unique_lock<std::mutex> lck(mutex_);
        return (int)map_.size();
    }
};

template <typename K, typename V>
class HiMapEx : public HiCollection<std::map<K, V>> {
  public:
    std::map<K, V> map_;
    std::mutex mutex_;

  public:
    bool insert(K k, V v) {
        std::unique_lock<std::mutex> lck(mutex_);
        auto it = map_.find(k);
        if (it != map_.end()) {
            return false;
        }
        map_[k] = v;
        return true;
    }

    bool find(K k, V *v) {
        std::unique_lock<std::mutex> lck(mutex_);
        auto it = map_.find(k);
        if (it == map_.end()) {
            return false;
        }
        v = &it->second;
        return true;
    }

    bool remove(K k) {
        std::unique_lock<std::mutex> lck(mutex_);
        auto it = map_.find(k);
        if (it != map_.end()) {
            return false;
        }
        map_.erase(k);
        return true;
    }

    bool exist(K k) {
        std::unique_lock<std::mutex> lck(mutex_);
        auto it = map_.find(k);
        return it != map_.end();
    }
};
} // namespace Hi